﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ProtocoloParasitracer
{
    class Program
    {
        static void Main (string [] args)
        {
            Console.Write(mkStringCmd("fin"));
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Write(mkStringCmd("fenable", "1024"));
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write(mkStringCmd("fdisable", "1024"));
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.Write(mkStringCmd("ftablesave"));
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write(mkStringCmd("fscript", "1024", "function () print('cajeta') end"));
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("Probando crear y leer 100.000 veces...");
            for (int i = 0; i < 100000; i++)
            {               
                readStringCmd(mkStringCmd("fenable", "1024"));
                readStringCmd(mkStringCmd("fdisable", "1024"));
                readStringCmd(mkStringCmd("ftablesave"));
                readStringCmd(mkStringCmd("fscript", "1024", "function () print('cajeta') end"));
            }
            Console.WriteLine("Ok!");
            Console.WriteLine("Presione una tecla para continuar...");
            Console.ReadLine ();
        }

        static byte [] mkCmd (params string [] partes)
        {
            return Encoding.ASCII.GetBytes(
                mkStringCmd(partes)
            );
        }

        static string mkStringCmd (params string [] partes)
        {
            if (partes == null)
                throw new ArgumentNullException("partes");

            StringBuilder sbCmd = new StringBuilder();

            sbCmd.Append("*");
            sbCmd.Append(partes.Length);
            sbCmd.Append("\r\n");

            foreach (string parte in partes)
            {
                sbCmd.Append("$");
                sbCmd.Append(parte.Length);
                sbCmd.Append("\r\n");
                sbCmd.Append(parte);
                sbCmd.Append("\r\n");
            }

            return sbCmd.ToString();
        }

        static void readStringCmd (string stringCmd)
        {
            int pos = 0;

            // *N (cantidad de argumentos)
            if (stringCmd[pos] != '*')
                throw new Exception("No empieza con *");
            pos++;

            int nArgs = 0;
            while (stringCmd[pos] != '\r')
            {
                nArgs = (nArgs * 10) + (stringCmd[pos]-'0');
                pos++;
            }

            // eat /r/n
            if (stringCmd[pos] != '\r')
                throw new Exception("Falta CR ");
            pos++;

            if (stringCmd[pos] != '\n')
                throw new Exception("Falta LF ");
            pos++;

            for (int i = 0; i < nArgs; i++)
            {
                // $N (cantidad de bytes de este argumento)
                if (stringCmd[pos] != '$')
                    throw new Exception("Falta $ ");
                pos++;

                int argLen = 0;
                while (stringCmd[pos] != '\r')
                {
                    argLen = (argLen * 10) + (stringCmd[pos]-'0');
                    pos++;
                }

                // eat /r/n
                if (stringCmd[pos] != '\r')
                    throw new Exception("Falta CR ");
                pos++;

                if (stringCmd[pos] != '\n')
                    throw new Exception("Falta LF ");
                pos++;

                // el argumento en si...
                StringBuilder arg = new StringBuilder();
                for (int j = 0; j < argLen; j ++)
                {
                    arg.Append(stringCmd[pos]);
                    pos ++;
                }

                if (stringCmd[pos] != '\r')
                    throw new Exception("Falta CR ");
                pos++;

                if (stringCmd[pos] != '\n')
                    throw new Exception("Falta LF ");
                pos++;
            }
        }

        static void eatChar (string @string, char c, ref int pos, string msgError)
        {
            //int foo = 1 / (stringCmd[pos++] == c ? 1 : 0);

            if (@string[pos] != c)
                throw new Exception(msgError);

            pos++;
        }
    }
}
